package system

import (
	"errors"
	"ltbz/cultural_tourism_api/models/system"
	"ltbz/cultural_tourism_api/utils"
	"strconv"
	"strings"
)

//MenuList 只返回当前登录管理员有权限的菜单列表，不返回按钮
func MenuList(sysUserInfo *system.SysUser) (list []*system.MenuListItemResp, err error, errMsg string) {
	//查询有权限的菜单
	roleMenu := new(system.SysRoleMenu)
	cond := " AND rm.role_id = ?"
	pars := make([]interface{}, 0)
	pars = append(pars, sysUserInfo.RoleId)
	roleHasMenuList, err := roleMenu.GetMenuListByCondition(cond, pars)
	if err != nil {
		errMsg = "查询角色绑定的菜单出错"
		err = errors.New(errMsg + "Err:" + err.Error())
		return
	}
	var menuIds []string
	for _, v := range roleHasMenuList {
		menuIds = append(menuIds, strconv.Itoa(int(v.MenuId)))
	}
	//查询其他级别的菜单列表
	menu := new(system.SysMenu)
	var condition, orderStr string
	par := make([]interface{}, 0)
	if len(menuIds) > 0 {
		condition = `AND menu_type = 0 AND menu_id IN(` + strings.Join(menuIds, ",") + `)`
		//par = append(par, menuIds)
		orderStr = "sort asc, create_time, menu_id desc"
	} else {
		errMsg = "无权限，请联系管理员"
		err = errors.New(errMsg)
		return
	}
	//遍历排序好的菜单列表，，返回每个菜单结点，不包含按钮类型
	childList, err := menu.GetMenuListByCondition(condition, par, orderStr)
	if err != nil {
		return
	}
	list = make([]*system.MenuListItemResp, 0)
	for _, v := range childList {
		tmp := &system.MenuListItemResp{
			MenuId:       v.MenuId,
			ParentId:     v.ParentId,
			Name:         v.Name,
			Sort:         v.Sort,
			Path:         v.Path,
			PathName:     v.PathName,
			IconPath:     v.IconPath,
			Component:    v.Component,
			Hidden:       v.Hidden,
			HiddenLayout: v.HiddenLayout,
			Level:        v.Level,
			MenuType:     v.MenuType,
			ButtonCode:   v.ButtonCode,
			CreateTime:   v.CreateTime.Format(utils.FormatDateTime),
			ModifyTime:   v.ModifyTime.Format(utils.FormatDateTime),
			HasBind:      true,
			Children:     nil,
		}
		list = append(list, tmp)
	}
	//组装返回值
	list = getMenuTreeRecursive(list, 0)
	return
}

func AllMenuList(req *system.MenuListReq, startSize, pageSize int) (count int, list []*system.MenuListItemResp, err error, errMsg string) {
	//查询一级菜单的数量和列表
	//查询其他级别的菜单列表
	menu := new(system.SysMenu)
	var condition string
	pars := make([]interface{}, 0)
	var finalRootIds []string
	if req.Name != "" {
		var rootIds []string
		name := "%" + req.Name + "%"
		relationList, tErr := menu.GetMenuByName(name)
		if tErr != nil {
			errMsg = "查询菜单出错"
			err = errors.New(errMsg + "Err:" + tErr.Error())
			return
		}
		if len(relationList) == 0 { //查不到相关记录
			return
		}
		for _, v := range relationList {
			if v.RootId == 0 {
				rootIds = append(rootIds, strconv.Itoa(int(v.MenuId)))
			} else {
				rootIds = append(rootIds, strconv.Itoa(int(v.RootId)))
			}
		}
		//分页处理 查询最顶层结点，得到最终的顶层结点
		condition = " AND parent_id=0 AND menu_id IN(" + strings.Join(rootIds, ",") + ")"
		//pars = append(pars, rootIds)
	} else {
		condition = " AND parent_id = 0"
	}

	count, err = menu.GetSysMenuPageCount(condition, pars)
	if err != nil {
		errMsg = "查询菜单列表出错"
		err = errors.New(errMsg + "Err:" + err.Error())
		return
	}
	rootList, err := menu.GetSysMenuPage(condition, pars, startSize, pageSize)
	if err != nil {
		errMsg = "查询菜单列表出错"
		err = errors.New(errMsg + "Err:" + err.Error())
		return
	}
	if len(rootList) == 0 { //查不到相关记录
		return
	}
	for _, v := range rootList {
		finalRootIds = append(finalRootIds, strconv.Itoa(int(v.MenuId)))
	}
	fCondition := ""
	fPars := make([]interface{}, 0)
	if req.HideLevel3 == 1 {
		fCondition += " AND level <=1 "
	}
	if req.HideButton == 1 {
		fCondition += " AND menu_type = 0"
	}
	finalRootIdsStr := strings.Join(finalRootIds, ",")
	//查询所有该顶层节点下的子节点
	fCondition += " AND (root_id IN(" + finalRootIdsStr + ") OR menu_id IN(" + finalRootIdsStr + "))"
	//fPars = append(fPars, finalRootIds, finalRootIds)
	orderStr := " sort ASC, create_time, menu_id DESC"
	childList, err := menu.GetMenuListByCondition(fCondition, fPars, orderStr)
	if err != nil {
		errMsg = "查询菜单列表出错"
		err = errors.New(errMsg + "Err:" + err.Error())
		return
	}
	list = make([]*system.MenuListItemResp, 0)
	for _, v := range childList {
		tmp := &system.MenuListItemResp{
			MenuId:       v.MenuId,
			ParentId:     v.ParentId,
			Name:         v.Name,
			Sort:         v.Sort,
			Path:         v.Path,
			PathName:     v.PathName,
			IconPath:     v.IconPath,
			Component:    v.Component,
			Hidden:       v.Hidden,
			HiddenLayout: v.HiddenLayout,
			Level:        v.Level,
			MenuType:     v.MenuType,
			ButtonCode:   v.ButtonCode,
			CreateTime:   v.CreateTime.Format(utils.FormatDateTime),
			ModifyTime:   v.ModifyTime.Format(utils.FormatDateTime),
			Children:     nil,
		}
		list = append(list, tmp)
	}

	//组装返回值
	list = getMenuTreeRecursive(list, 0)
	return
}

func getMenuTreeRecursive(list []*system.MenuListItemResp, parentId int64) []*system.MenuListItemResp {
	res := make([]*system.MenuListItemResp, 0)
	for _, v := range list {
		if v.ParentId == parentId {
			v.Children = getMenuTreeRecursive(list, v.MenuId)
			res = append(res, v)
		}
	}
	return res
}

//ButtonList 只返回当前登录管理员有权限的按钮列表，不返回按钮
func ButtonList(roleId int64, req *system.MenuShortListItem) (list []*system.SysMenu, err error, errMsg string) {
	//查询有权限的菜单
	roleMenu := new(system.SysRoleMenu)
	cond := " AND rm.role_id = ?"
	pars := make([]interface{}, 0)
	pars = append(pars, roleId)
	roleHasMenuList, err := roleMenu.GetMenuListByCondition(cond, pars)
	if err != nil {
		errMsg = "查询角色绑定的菜单出错"
		err = errors.New(errMsg + "Err:" + err.Error())
		return
	}
	var menuIds []string
	for _, v := range roleHasMenuList {
		menuIds = append(menuIds, strconv.Itoa(int(v.MenuId)))
	}
	//查询其他级别的菜单列表
	menu := new(system.SysMenu)
	var condition string
	par := make([]interface{}, 0)
	condition = ` AND menu_type = 1 AND menu_id IN(` + strings.Join(menuIds, ",") + `) `
	//par = append(par, menuIds)
	if req.MenuId > 0 {
		condition += " AND parent_id = ?"
		par = append(par, req.MenuId)
	}
	//遍历排序好的菜单列表，，返回每个菜单结点，不包含按钮类型
	list, err = menu.GetMenuListByCondition(condition, par, "")
	if err != nil {
		errMsg = "查询菜单按钮列表出错"
		err = errors.New(errMsg + "Err:" + err.Error())
		return
	}
	return
}

// DeleteMenu 删除菜单，连同删除子菜单
func DeleteMenu(req *system.MenuShortListItem) (err error, errMsg string) {
	menu := new(system.SysMenu)
	//找出当前层级，如果当前是最顶层，则批量删除和顶层相关的所有部门
	menuInfo, err := menu.GetMenuByMenuId(req.MenuId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			errMsg = "菜单不存在或者已删除"
			err = errors.New(errMsg + "Err:" + err.Error())
			return
		}
		errMsg = "查询菜单出错"
		err = errors.New(errMsg + "Err:" + err.Error())
		return
	}
	if menuInfo.ParentId > 0 {
		//如果不是最顶层，则构建树形图，得到需要删除的menu_id
		//查询所有该顶层节点下的子节点
		fCondition := " AND root_id = ? OR menu_id = ?"
		fPars := make([]interface{}, 0)
		fPars = append(fPars, menuInfo.RootId, menuInfo.RootId)
		orderStr := " level DESC "
		childList, tErr := menu.GetMenuListByCondition(fCondition, fPars, orderStr)
		if tErr != nil {
			errMsg = "查询菜单列表出错"
			err = errors.New(errMsg + "Err:" + tErr.Error())
			return
		}

		menuIdMap := make(map[int64][]string)
		for _, v := range childList {
			menuIdMap[v.MenuId] = append(menuIdMap[v.MenuId], strconv.Itoa(int(v.MenuId)))
			if v.ParentId > 0 {
				menuIdMap[v.ParentId] = append(menuIdMap[v.ParentId], menuIdMap[v.MenuId]...)
			}
		}
		menuIdArr := menuIdMap[menuInfo.MenuId]
		if len(menuIdArr) > 0 {
			cond := " AND menu_id IN(" + strings.Join(menuIdArr, ",") + ") "
			pars := make([]interface{}, 0)
			//pars = append(pars, menuIdMap[menuInfo.MenuId])
			err = menu.DeleteByCondition(cond, pars)
		}
	} else {
		//如果是最顶层，则删除所有相关的menu_id
		cond := " AND menu_id = ? OR root_id = ? "
		pars := make([]interface{}, 0)
		pars = append(pars, menuInfo.MenuId, menuInfo.MenuId)
		err = menu.DeleteByCondition(cond, pars)
	}
	return
}
